/*-------------------------------*- C++ -*-----------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     |
    \\  /    A nd           | www.openfoam.com
     \\/     M anipulation  |
-------------------------------------------------------------------------------
    Copyright (C) 2011 OpenFOAM Foundation
    Copyright (C) 2018-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
    This file is part of OpenFOAM.

    OpenFOAM is free software: you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    for more details.

    You should have received a copy of the GNU General Public License
    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.

Description
    Define the globals used in the OpenFOAM library.
    It is important that these are constructed in the appropriate order to
    avoid the use of unconstructed data in the global namespace.

    This file has a '.Cver' extension to trigger a Makefile rule to replace
    'BUILD', 'VERSION' tags with the corresponding strings.

\*---------------------------------------------------------------------------*/

#include "foamVersion.H"
#include "endian.H"
#include "label.H"
#include "scalar.H"

// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //

namespace
{

// Extract value from "tag=<digits>", eg "LSB;label=32;scalar=64"
// Return 0 on any errors
static inline unsigned getTaggedSize(const char* tag, const std::string& s)
{
    auto first = s.find(tag);
    if (first == std::string::npos) return 0;

    first = s.find('=', first);
    if (first == std::string::npos) return 0;
    ++first;

    auto last = s.find_first_not_of("0123456789", first);
    if (last == first) return 0;

    return std::stoul(s.substr(first, last));
}

} // End namespace anonymous


// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //

// Value of OPENFOAM defined in wmake rules
const int Foam::foamVersion::api
{
    OPENFOAM
};


// Value of PATCH generated by the build-script
const std::string Foam::foamVersion::patch
{
    "@PATCH@"
};


// Value of BUILD generated by the build-script
const std::string Foam::foamVersion::build
{
    "@BUILD@"
};


// Information about machine endian, label and scalar sizes
const std::string Foam::foamVersion::buildArch
{
#ifdef WM_LITTLE_ENDIAN
    "LSB"
#elif defined (WM_BIG_ENDIAN)
    "MSB"
#else
#warning Cannot determine BIG or LITTLE endian. This should never happen.
    "_SB"
#endif
    ";label="  + std::to_string(8*sizeof(Foam::label))
  + ";scalar=" + std::to_string(8*sizeof(Foam::scalar))
#ifdef WM_SPDP
  + ";solveScalar=" + std::to_string(8*sizeof(Foam::solveScalar))
#endif
};


// Value of VERSION generated by the build-script
// Only required for compatibility
const std::string Foam::foamVersion::version
{
    "@VERSION@"
};


// * * * * * * * * * * * * * * * Global Functions  * * * * * * * * * * * * * //

unsigned Foam::foamVersion::labelByteSize(const std::string& str)
{
    return getTaggedSize("label=", str) / 8;
}


unsigned Foam::foamVersion::scalarByteSize(const std::string& str)
{
    return getTaggedSize("scalar=", str) / 8;
}


// These two are defined as functions to avoid static initialization
// order problems with older gcc.

std::string Foam::foamVersion::configuredProjectDir()
{
#ifdef FOAM_CONFIGURED_PROJECT_DIR
    return FOAM_CONFIGURED_PROJECT_DIR ;
#else
    return std::string{};
#endif
}


std::string Foam::foamVersion::configuredEtcDir()
{
#ifdef FOAM_CONFIGURED_PROJECT_ETC
    return FOAM_CONFIGURED_PROJECT_ETC ;
#else
    return std::string{};
#endif
}


// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Setup an error handler for the global new operator

#include "new.C"

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// The nullObject singleton and a dummy zero singleton

#include "nullObject.C"
#include "zero.C"

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Global IO streams

#include "IOstreams.C"

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

#include "JobInfo.H"
bool Foam::JobInfo::constructed(false);

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Global error definitions (initialised by construction)

#include "messageStream.C"
#include "error.C"
#include "IOerror.C"
#include "token.C"

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Read the debug and info switches

#include "debug.C"

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Read file modification checking switches

#include "regIOobject.C"

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Read parallel communication switches

#include "UPstream.C"

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Read constants

#include "constants.C"
#include "dimensionedConstants.C"

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Create the jobInfo file in the $FOAM_JOB_DIR/runningJobs directory

#include "JobInfo.C"

// ************************************************************************* //
